// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------
// Modification history:
// feature: listener code decoupling
// feature: content filter topic
// feature: Unified Transport Abstraction Layer Unified Transport Abstraction Layer
// feature: add statictic lookup
// feature: simplify xml profile
// ------------------------------------------------------------------

#ifndef INCLUDE_EDDS_RTPS_ATTRIBUTES_RTPSPARTICIPANTATTRIBUTES_H_
#define INCLUDE_EDDS_RTPS_ATTRIBUTES_RTPSPARTICIPANTATTRIBUTES_H_

#include <edds/rtps/attributes/PropertyPolicy.h>
#include <edds/rtps/attributes/ServerAttributes.h>
#include <ertps/utils/LocatorAlias.h>
#include <edds/rtps/common/PortParameters.h>
#include <edds/rtps/common/Time_t.h>
#include <edds/rtps/resources/ResourceManagement.h>
#include <transport/TransportDescriptorInterface.h>

#include <memory>
#include <sstream>

#include <edds/rtps/attributes/ExternalLocators.hpp>
#include <edds/rtps/attributes/RTPSParticipantAllocationAttributes.hpp>
#include <edds/rtps/flowcontrol/FlowControllerDescriptor.hpp>
#include <ertps/utils/fixed_size_string.hpp>

#include <xmlparser/attributes/XMLRTPSParticipantAttributes.h>

namespace evbs {

namespace edds {

namespace rtps {

using ParticipantType = vbsutil::xmlparser::ParticipantType;

} /* namespace rtps */
} /* namespace edds */

namespace ertps {
namespace rtps {
using DiscoveryProtocol = vbsutil::xmlparser::DiscoveryProtocol;
using vbsutil::xmlparser::DiscoveryProtocol_t;

using ParticipantFilteringFlags = vbsutil::xmlparser::ParticipantFilteringFlags;
using vbsutil::xmlparser::ParticipantFilteringFlags_t;
using ContentFilterProperty = vbsutil::xmlparser::ContentFilterProperty;

//! PDP factory for EXTERNAL type
class PDP;
class BuiltinProtocols;

typedef struct _PDPFactory {
    // Pointer to the PDP creator
    PDP* (*CreatePDPInstance)(BuiltinProtocols*);
    // Pointer to the PDP destructor
    void (*ReleasePDPInstance)(PDP*);

    bool operator==(const struct _PDPFactory& e) const {
        return (CreatePDPInstance == e.CreatePDPInstance) && (ReleasePDPInstance == e.ReleasePDPInstance);
    }

} PDPFactory;

using SimpleEDPAttributes = vbsutil::xmlparser::SimpleEDPAttributes;

using InitialAnnouncementConfig = vbsutil::xmlparser::InitialAnnouncementConfig;

using DiscoverySettings = vbsutil::xmlparser::DiscoverySettings;

using LookupSettings = vbsutil::xmlparser::LookupSettings;

using BuiltinAttributes = vbsutil::xmlparser::BuiltinAttributes;

/**
 * Class RTPSParticipantAttributes used to define different aspects of a RTPSParticipant.
 *@ingroup RTPS_ATTRIBUTES_MODULE
 */
class RTPSParticipantAttributes {
    using FlowControllerDescriptorList = std::vector<std::shared_ptr<edds::rtps::FlowControllerDescriptor>>;

 public:
    RTPSParticipantAttributes() {
        setName("RTPSParticipant");
        sendSocketBufferSize = 0U;
        listenSocketBufferSize = 0U;
        participantID = -1;
        useBuiltinTransports = true;
        transport_type = TRANSPORT_TYPE_AUTO;
    }

    virtual ~RTPSParticipantAttributes() {}

    RTPSParticipantAttributes& operator=(vbsutil::xmlparser::RTPSParticipantAttributes& xmlAttr) {
        defaultUnicastLocatorList = xmlAttr.defaultUnicastLocatorList;
        defaultMulticastLocatorList = xmlAttr.defaultMulticastLocatorList;
        default_external_unicast_locators = xmlAttr.default_external_unicast_locators;
        ignore_non_matching_locators = xmlAttr.ignore_non_matching_locators;
        sendSocketBufferSize = xmlAttr.sendSocketBufferSize;
        listenSocketBufferSize = xmlAttr.listenSocketBufferSize;
        prefix = xmlAttr.prefix;
        builtin = xmlAttr.builtin;
        port = xmlAttr.port;
        participantID = xmlAttr.participantID;
        // userTransports = xmlAttr.userTransports; xml中的qos只保存了字符串，需要重新填充
        // (void)fillTransportAttributes(userTransports, xmlAttr.userTransports);
        useBuiltinTransports = xmlAttr.useBuiltinTransports;
        transport_type = xmlAttr.transport_type;
        allocation = xmlAttr.allocation;
        properties = xmlAttr.properties;
        flow_controllers = xmlAttr.flow_controllers;
        setName(xmlAttr.getName());

        return *this;
    }

    bool operator==(const RTPSParticipantAttributes& b) const {
        return (this->name == b.name) && (this->defaultUnicastLocatorList == b.defaultUnicastLocatorList) &&
               (this->defaultMulticastLocatorList == b.defaultMulticastLocatorList) &&
               (this->default_external_unicast_locators == b.default_external_unicast_locators) &&
               (this->ignore_non_matching_locators == b.ignore_non_matching_locators) &&
               (this->sendSocketBufferSize == b.sendSocketBufferSize) &&
               (this->listenSocketBufferSize == b.listenSocketBufferSize) && (this->builtin == b.builtin) &&
               (this->port == b.port) && (this->participantID == b.participantID) &&
               (this->useBuiltinTransports == b.useBuiltinTransports) && (this->properties == b.properties) &&
               (this->prefix == b.prefix) && (this->flow_controllers == b.flow_controllers);
    }

    /**
     * Default list of Unicast Locators to be used for any Endpoint defined inside this
     * RTPSParticipant in the case that it was defined with NO UnicastLocators. At least ONE locator
     * should be included in this list.
     */
    LocatorList_t defaultUnicastLocatorList;

    /**
     * Default list of Multicast Locators to be used for any Endpoint defined inside this
     * RTPSParticipant in the case that it was defined with NO MulticastLocators. This is usually
     * left empty.
     */
    LocatorList_t defaultMulticastLocatorList;

    /**
     * The collection of external locators to use for communication on user created topics.
     */
    edds::rtps::ExternalLocators default_external_unicast_locators;

    /**
     * Whether locators that don't match with the announced locators should be kept.
     */
    bool ignore_non_matching_locators = false;

    /*!
     * @brief Send socket buffer size for the send resource. Zero value indicates to use default
     * system buffer size. Default value: 0.
     */
    uint32_t sendSocketBufferSize;

    /*! Listen socket buffer for all listen resources. Zero value indicates to use default system
     * buffer size. Default value: 0.
     */
    uint32_t listenSocketBufferSize;

    //! Optionally allows user to define the GuidPrefix_t
    GuidPrefix_t prefix;

    RTPS_DllAPI inline bool ReadguidPrefix(const char* pfx) { return bool(std::istringstream(pfx) >> prefix); }

    //! Builtin parameters.
    BuiltinAttributes builtin;

    //! Port Parameters
    PortParameters port;

    //! Participant ID
    int32_t participantID;

    //! User defined transports to use alongside or in place of builtins.
    std::vector<std::shared_ptr<vbs::transport::TransportDescriptorInterface>> userTransports;

    //! Set as false to disable the default UDPv4 implementation.
    bool useBuiltinTransports;

    ertps::rtps::TransportTypeKind transport_type;

    //! Holds allocation limits affecting collections managed by a participant.
    RTPSParticipantAllocationAttributes allocation;

    //! Property policies
    PropertyPolicy properties;

    //! Set the name of the participant.
    inline void setName(const char* nam) { name = nam; }

    //! Get the name of the participant.
    inline const char* getName() const { return name.c_str(); }

    //! Flow controllers.
    FlowControllerDescriptorList flow_controllers;

 private:
    //! Name of the participant.
    string_255 name;
};

} /* namespace rtps */
} /* namespace ertps */
} /* namespace evbs */

#endif  // INCLUDE_EDDS_RTPS_ATTRIBUTES_RTPSPARTICIPANTATTRIBUTES_H_
